﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CPPEI.Coolzon.Data.MainServiceData;
using CPPEI.Coolzon.Service.Contract;
using CPPEI.Coolzon.Server.CacheData;
using CPPEI.Coolzon.Data;
using CPPEI.Coolzon.Common;

namespace CPPEI.Coolzon.Server.ServiceImplement
{
    class SingletonModeReconnectStrategy
    {
        internal RespReconnectData Reconnect4NoneOperator(Request request, ReqReconnectData requestData)
        {
            RespReconnectData responseData = new RespReconnectData();
            responseData.ServerIP = CZEnvironment.Instance.ServerIP;
            responseData.ServerPort = CZEnvironment.Instance.ServerPort;

            CacheData.ControlDomain domain = CacheData.ServerData.Instance.GetExistsDomain();
            if (domain == null)
            {
                #region // 失败，域不存在
                responseData.IsSuccess = false;
                responseData.Message = "重连失败，域不存在";
                Common.Logger.WarningToTag("Handler", "请求重新连接失败，域不存在,useridentity:{0},domainid:{1},solution:{2},operatorId:{3}",
                    requestData.UserIdentity,
                    requestData.DomainId,
                    requestData.SolutionName,
                    requestData.OperatorIdentity);
                return responseData;
                #endregion
            }

            Client consoleClient = domain.GetConsoleClient();
            if (consoleClient != null && consoleClient.Callback != null)
            {
                if (CacheDataUtil.IsLiveTimeout(consoleClient))
                {
                    #region// 终端不为空，callback不为空，但是最新活跃时间太久，可能掉线，视为不存在
                    responseData.IsSuccess = false;
                    responseData.Message = "重连失败,服务器中的操作员可能以断线";
                    Common.Logger.WarningToTag("Handler", "请求重新连接失败，服务器中的操作员可能以断线,useridentity:{0},domainid:{1},solution:{2},operatorId:{3}",
                        requestData.UserIdentity,
                        requestData.DomainId,
                        requestData.SolutionName,
                        requestData.OperatorIdentity);
                    return responseData;
                    #endregion
                }
            }
            else
            {
                responseData.IsSuccess = false;
                responseData.Message = "重连失败,服务器中不存在操作员";
                Common.Logger.WarningToTag("Handler", "请求重新连接失败，服务器中不存在操作员,useridentity:{0},domainid:{1},solution:{2},operatorId:{3}",
                    requestData.UserIdentity,
                    requestData.DomainId,
                    requestData.SolutionName,
                    requestData.OperatorIdentity);
                return responseData;
            }
            if(string.IsNullOrWhiteSpace(domain.MainServerIP) || domain.MainServerPort == 0)
            {
                responseData.IsSuccess = false;
                responseData.Message = "重连失败,服务器中不存在主服务器信息";
                Common.Logger.WarningToTag("Handler", "请求重新连接失败，服务器中主服务器信息,useridentity:{0},domainid:{1},solution:{2},operatorId:{3}",
                    requestData.UserIdentity,
                    requestData.DomainId,
                    requestData.SolutionName,
                    requestData.OperatorIdentity);
                return responseData;
            }
            responseData.MainServerIP = domain.MainServerIP;
            responseData.MainServerPort = domain.MainServerPort;
            responseData.OperatorIdentity = domain.OperatorIdentity;
            responseData.DomainID = domain.Id;

            CacheData.Client client = CacheData.ServerData.Instance.GetClient(requestData.UserIdentity);
            if (client == null)
            {
                #region 用户不存在在内存里
                // 用户不存在于服务器的客户单列表中，这种情况主要是由于服务器重新启动导致
                // 从服务器上创建用户对象，然后添加到服务器的客户端列表中
                client = new Client();
                client.UserIdentity = requestData.UserIdentity;
                client.UserAccount = requestData.UserAccount;
                client.AppType = requestData.AppType;
                // 设置客户端的最后活跃时间
                // 否则将会在并发的重连接中被下一个终端个移除掉
                client.LatestActiveTicks = DateTime.Now.Ticks;
                // 设置终端的控制状态
                if (requestData.ControlState == Service.Contract.ControlState.UnderControl)
                {
                    client.ControlState = CacheData.ControlState.UnderControl;
                }
                else
                {
                    client.ControlState = CacheData.ControlState.OutOfControl;
                }

                if (CacheData.ServerData.Instance.AddClient(client))
                {
                    // 设置控制端的状态为正在重新连接
                    client.State = ClientState.InDomain;
                    // 获取控制端的回调接口实例
                    client.Callback = System.ServiceModel.OperationContext.Current.GetCallbackChannel<Coolzon.Service.IMainServiceCallback>();

                    responseData.IsSuccess = true;
                }
                else
                {
                    // 添加用户到服务器列表出错，服务器的客户端列表已满
                    responseData.IsSuccess = false;
                    responseData.Message = "重连失败,服务器中的客户端数量已满";
                    client = null;
                }
                #endregion
            }
            else
            {
                client.LatestActiveTicks = DateTime.Now.Ticks;
                client.Callback = System.ServiceModel.OperationContext.Current.GetCallbackChannel<Coolzon.Service.IMainServiceCallback>();
                responseData.IsSuccess = true;
            }

            if (client != null)
            {
                domain.ExistReplaceNotExistAdd(client);
                //服务器为主服务并且方案不同，则通知client更新方案,但是重连操作设置成失败，否则场景不能同步
                if (string.Equals(domain.MainServerIP, CZEnvironment.Instance.ServerIP) && domain.MainServerPort == CZEnvironment.Instance.ServerPort && !string.Equals(domain.SolutionName, requestData.SolutionName))
                {
                    NotifyClientSwitchSolution(client, domain.SolutionName, request);
                    responseData.IsSuccess = false;
                    responseData.Message = "通知client更新方案，重连失败，等待下次重连更新场景";
                    Common.Logger.WarningToTag("Handler", "请求重新连接失败，需要更新方案，等待下次重连更新场景,useridentity:{0},domainid:{1},solution:{2},operatorId:{3}",
                        requestData.UserIdentity,
                        requestData.DomainId,
                        requestData.SolutionName,
                        requestData.OperatorIdentity);
                }
                else
                {
                    responseData.ViewStateAge = domain.ViewStateAge;
                    responseData.ViewStateToken = domain.ViewStateToken;
                    responseData.IsSuccess = true;
                }
            }
            return responseData;
        }
        
        /// <summary>
         /// 通知自己切换方案
         /// </summary>
         /// <param name="request"></param>
         /// <param name="domain"></param>
         /// <param name="responseData"></param>
        private void NotifyClientSwitchSolution(CacheData.Client client, string solutionName, Data.MainServiceData.Request request)
        {
            RespSwitchSolutionData responseData = new RespSwitchSolutionData();
            responseData.SolutionName = solutionName;

            Response response = new Response();
            response.Header = new ResponseHeader();
            response.Data = SerializeUtility.SerializeToBinary(responseData);
            response.Header.Scenario = Service.Contract.RESPONSE_SCENARIO.SOLUTION;
            response.Header.Command = Service.Contract.RESPONSE_COMMAND.SOLUTION.SWITCH;
            response.Header.SendTicks = DateTime.Now.Ticks;
            response.Header.DataLength = response.Data.Length;
            response.Header.RequestHeader = request.Header;
            try
            {
                client.Callback.OnReceiveResponse(response);
            }
            catch (Exception ex)
            {
                Common.Logger.ErrorToTag("MainService", "通知用户{0},里有终端的状态改变失败:{2}",
                    client.UserIdentity,
                    ex);
                client.Callback = null;
            }
        }

        internal RespReconnectData Reconnect4Operator(Data.MainServiceData.Request request, ReqReconnectData requestData)
        {
            RespReconnectData responseData = new RespReconnectData();
            responseData.ServerIP = CZEnvironment.Instance.ServerIP;
            responseData.ServerPort = CZEnvironment.Instance.ServerPort;

            CacheData.Client client = CacheData.ServerData.Instance.GetClient(requestData.UserIdentity);
            if (client == null)
            {
                #region 用户不存在在内存里
                // 用户不存在于服务器的客户单列表中，这种情况主要是由于服务器重新启动导致
                // 从服务器上创建用户对象，然后添加到服务器的客户端列表中
                client = new Client();
                client.UserIdentity = requestData.UserIdentity;
                client.UserAccount = requestData.UserAccount;
                client.AppType = requestData.AppType;
                // 设置客户端的最后活跃时间
                // 否则将会在并发的重连接中被下一个终端个移除掉
                client.LatestActiveTicks = DateTime.Now.Ticks;
                // 设置终端的控制状态
                if (requestData.ControlState == Service.Contract.ControlState.UnderControl)
                {
                    client.ControlState = CacheData.ControlState.UnderControl;
                }
                else
                {
                    client.ControlState = CacheData.ControlState.OutOfControl;
                }

                if (CacheData.ServerData.Instance.AddClient(client))
                {
                    // 设置控制端的状态为正在重新连接
                    client.State = ClientState.InDomain;
                    // 获取控制端的回调接口实例
                    client.Callback = System.ServiceModel.OperationContext.Current.GetCallbackChannel<Coolzon.Service.IMainServiceCallback>();
                    responseData.IsSuccess = true;
                }
                else
                {
                    // 添加用户到服务器列表出错，服务器的客户端列表已满
                    responseData.IsSuccess = false;
                    responseData.Message = "重连失败,服务器中的客户端数量已满";
                    client = null;
                }
                #endregion
            }
            else
            {
                client.LatestActiveTicks = DateTime.Now.Ticks;
                client.Callback = System.ServiceModel.OperationContext.Current.GetCallbackChannel<Coolzon.Service.IMainServiceCallback>();
                responseData.IsSuccess = true;
            }

            if (client != null)
            {
                CacheData.ControlDomain domain = CacheData.ServerData.Instance.GetExistsDomain();
                if (domain == null)
                {
                    #region 创建域
                    lock (CacheData.ServerData.S_DOMAINLISTLOCKOBJ)
                    {
                        domain = new CacheData.ControlDomain();
                        domain.Id = CacheData.ServerData.UniqueDomainId;
                        domain.Caption = requestData.DomainCaption;
                        domain.SolutionName = requestData.SolutionName;
                        domain.SolutionCaption = requestData.SolutionCaption;
                        if (!CacheData.ServerData.Instance.CreateDomain(domain))
                        {
                            // 创建域失败
                            responseData.IsSuccess = false;
                            responseData.Message = "重连失败,创建域失败";
                            domain = null;
                            Common.Logger.ErrorToTag("Handler", "请求重新连接,创建域失败,useridentity:{0},domainid:{1},solution:{2},operatorId:{3}",
                                requestData.UserIdentity,
                                requestData.DomainId,
                                requestData.SolutionName,
                                requestData.OperatorIdentity);
                        }
                        else
                        {
                            domain.AddClient(client);
                        }
                    }
                    #endregion
                }
                else
                {
                    domain.ExistReplaceNotExistAdd(client);
                }

                if (domain != null)
                {
                    domain.UpdateMainServer(requestData.MainServerIP, requestData.MainServerPort);
                    domain.UpdateViewState(requestData.SolutionName, requestData.ViewStateAge, requestData.ViewStateToken);
                    domain.SetOperator(client);

                    responseData.MainServerIP = domain.MainServerIP;
                    responseData.MainServerPort = domain.MainServerPort;
                    responseData.OperatorIdentity = domain.OperatorIdentity;
                }
            }

            return responseData;
        }
    }
}
